package com.imooc.searchcountdown;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 通过这种方式 仍是串行来执行
 * @author ChangLiang
 * @date 2019/3/5
 */
public class App2 {

    private static Integer corePoolSize = 4;

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();

        long start = System.currentTimeMillis();

        EsService esService = new EsService();

        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("request-pool-%d").build();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                10,
                0L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(20),
                threadFactory,
                new ThreadPoolExecutor.AbortPolicy()
        );

        // 启动一个线程去执行items
        try {
            CallFutureMethod(esService,"searchQueryItems",new Class<?>[]{String.class},new
                            Object[]{"changliang"},threadPoolExecutor,list);
        } catch (Exception e) {
            e.printStackTrace();
        }


        // 启动一个线程去执行guides
        try {
            CallFutureMethod(esService,"searchQueryGuides",new Class<?>[]{String.class},new
                    Object[]{"changliang"},threadPoolExecutor,list);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 启动一个线程去执行applications
        try {
            CallFutureMethod(esService,"getApplications",new Class<?>[]{String.class},new
                    Object[]{"changliang"},threadPoolExecutor,list);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 启动一个线程去执行appoints
        try {
            try {
                CallFutureMethod(esService,"getAppointItems",new Class<?>[]{String.class},new
                        Object[]{"changliang"},threadPoolExecutor,list);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();

        System.out.println((end - start));
        System.out.println(list);
    }

    private static void CallFutureMethod(final Object target, final String methodName, final Class<?>[]
            parameterTypes,final Object[]params, ThreadPoolExecutor threadPoolExecutor, List<String> list) {
        // 启动一个线程去执行items 如果2秒内没有返回值 则停止线程
        FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {

            @Override
            public String call() throws Exception {

                String value;

                try {
                    Method method = target.getClass().getDeclaredMethod(methodName, parameterTypes);
                    Object returnValue = method.invoke(target, params);
                    value = returnValue != null ? returnValue.toString() : null ;
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    throw e ;
                } catch (SecurityException e) {
                    e.printStackTrace();
                    throw e ;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw e ;
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                    throw e ;
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    throw e ;
                }
                return value;
            }
        });
        threadPoolExecutor.execute(futureTask);
        String result= null;

        try {
            /**获取方法返回值 并设定方法执行的时间为10秒*/
            result = futureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            futureTask.cancel(true);
            System.out.println("方法执行中断");
        } catch (ExecutionException e) {
            futureTask.cancel(true);
            System.out.println("Execution异常");
        } catch (TimeoutException e) {
            futureTask.cancel(true);
            throw new RuntimeException("invoke timeout", e);
        }
        if (result != null) {
            list.add(result);
        }
    }
}
